# -*- coding: utf-8 -*-
# standard
import os
import sys
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from email.mime.base import MIMEBase
from email import encoders

# third
from sqlalchemy import BigInteger

# local
_P_PATH =  os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
if _P_PATH not in sys.path:
    sys.path.append(_P_PATH)
from base_model import *


"""
@Title:   邮件模块(目前仅有发送邮件功能)
@File: email_model.py
@Author: walle 2025年03日24日 09时14分44秒
@Version: 1.0.0
@Desc: 
"""


class EmailSendStatus(MyEnum):
    NOT_SEND: str = "未发送"
    SEND_SUCCESS: str = "发送成功"
    SEND_FAIL: str = "发送失败"


class EmailSendRecordOrm(Base, OrmTools):
    __tablename__ = "email_send_record"
    __table_args__ = (
        {'comment': '邮件发送记录表'}
    )
    id = Column(BigInteger, primary_key=True, autoincrement=True, comment="主键")
    from_email = Column(String(63), nullable=False, comment="发件人邮箱")
    to_email = Column(String(63), nullable=False, comment="收件人邮箱")
    cc_email = Column(ARRAY(String(63), dimensions=1), nullable=True, default=list, comment="抄送人邮箱")
    bcc_email = Column(ARRAY(String(63), dimensions=1), nullable=True, default=list, comment="密送人邮箱")
    subject = Column(String(127), nullable=False, comment="邮件主题")
    content = Column(Text, nullable=False, comment="邮件内容")
    attachments = Column(ARRAY(String(255), dimensions=1), nullable=True, default=list, comment="附件")
    send_time = Column(DateTime, nullable=False, onupdate=datetime.now, comment="发送时间")
    create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间")
    status = Column(String(15), nullable=False, default=EmailSendStatus.NOT_SEND.value, comment="发送状态: EmailSendStatus")
    reason = Column(String(255), nullable=True, default=None, comment="失败原因")

    @classmethod
    def add_one(cls, from_email: str, to_email: str, subject: str, content: str,
                cc_email: List[str] | None = None, bcc_email: List[str] | None= None,
                attachments: List[str] | None = None, db_session: Session | None = None) -> Resp:
        resp = Resp()
        db_session, need_close = (new_db_session(sync=True), True) if db_session is None else (db_session, False)
        one = cls(from_email=from_email, to_email=to_email, 
                  cc_email=cc_email, bcc_email=bcc_email,
                subject=subject, content=content, attachments=attachments)
        db_session.add(one)
        db_session.commit()
        db_session.refresh(one)
        resp.data = one.id
        if need_close:    
            db_session.close()
        return resp




class EmailHandler(BaseModel):
    email: str = Field("service@ihcc.com.cn", description="邮箱地址")
    password: str = Field("GRbB44CPcFGy4mRC", description="邮箱密码")
    smtp_server: str = Field("smtp.exmail.qq.com", description="SMTP服务器地址")
    smtp_port: int = Field(465, description="SMTP服务器端口")
    imap_server: str = Field("imap.exmail.gg.com", description="IMAP服务器地址")
    imap_port: int = Field(993, description="IMAP服务器端口")

    def login_smtp(self) -> Optional[smtplib.SMTP_SSL]:
        handler = smtplib.SMTP_SSL(host=self.smtp_server, port=self.smtp_port, timeout=10)
        handler.set_debuglevel(1)  # 开启调试模式
        try:
            result = handler.login(user=self.email, password=self.password)
        except Exception as e:
            result = e.args
            logger.error(f"登录失败: {self.smtp_server} {self.smtp_port} {e}")
        finally:
            if len(result) == 2 and result[0] == 235:
                logger.debug(f"登录成功: {result}")
            else:
                handler.quit()
                handler = None
                logger.error(f"登录失败: {self.smtp_server} {self.smtp_port} {result}")
        return handler
    
    def generate_mail(self, subject: str, content: str, to: str, cc: List[str] | None = None,
                     bcc: List[str] | None = None, attachments: List[str] | None = None) -> MIMEMultipart:
        msg = MIMEMultipart()
        msg['From'] = self.email
        msg['To'] = to
        msg['Cc'] = ";".join(cc) if cc else ""
        msg['Bcc'] =  ";".join(bcc) if bcc else ""
        msg['Subject'] = subject
        msg.attach(MIMEText(content, 'html', 'utf-8'))
        if attachments:
            for attachment in attachments:
                with open(attachment, 'rb') as f:
                    mime = MIMEBase('application', 'octet-stream')
                    mime.set_payload(f.read())
                    encoders.encode_base64(mime)
                    mime.add_header('Content-Disposition', 'attachment', filename=os.path.basename(attachment))
                    msg.attach(mime)
        return msg

    def send(self, subject: str, 
             content: str, to: str, 
             cc: List[str] | None = None,
             bcc: List[str] | None = None,
             attachments: List[str] | None = None) -> Resp:
        handler = self.login_smtp()
        resp = Resp()
        kw = {
            "from_email": self.email,
            "to_email": to,
            "subject": subject,
            "content": content,
            "cc_email": cc,
            "bcc_email": bcc,
            "attachments": attachments,
        }
        if handler is None:
            kw['status'] = EmailSendStatus.SEND_FAIL.value
            kw['reason'] = "登录失败"
            resp.message = kw['reason']      
        else:
            mail = self.generate_mail(subject=subject, content=content, 
                                    to=to, cc=cc, bcc=bcc, attachments=attachments)
            try:
                handler.sendmail(self.email, [to] + (cc if cc else []) + (bcc if bcc else []), mail.as_string())
                kw['status'] = EmailSendStatus.SEND_SUCCESS.value
            except Exception as e:
                kw['status'] = EmailSendStatus.SEND_FAIL.value
                kw['reason'] = str(e)
                resp.message = kw['reason']
            finally:
                ... # todo: 记录邮件发送记录


        



EMAIL = EmailHandler()


if __name__ == '__main__':
    EMAIL.send(subject="测试邮件", content="这是一封测试邮件", to="xulijie@ihcc.com.cn", cc=['xulijie2002@163.com'], bcc=['583736361@qq.com'])
    pass